grammar SysY;

import SysyLex;

program : compUnit EOF;

//编译单元: 函数声明+声明
compUnit
    : (decl | funcDef)*
    ;

//声明：常量声明+变量声明
decl
    : constDecl
    | varDecl
    ;

//常量声明
constDecl : Const bType constDef (Comma constDef)* Semicolon;

//基本类型
bType
    : Int  # int
    | Float  # float
    ;

//常数定义
constDef : Ident (Lbracket exp Rbracket)* Assign initVal;

//变量声明
varDecl : bType varDef (Comma varDef)* Semicolon;

//变量定义
varDef : Ident (Lbracket exp Rbracket)* (Assign initVal)?;

//变量初值
initVal
    : exp  # init
    | Lbrace (initVal (Comma initVal)*)? Rbrace  # initList
    ;

//函数定义
funcDef : funcType Ident Lparen funcFParams? Rparen block;

//函数类型
funcType
    : bType  # funcType_
    | Void  # void
    ;

//函数形参表
funcFParams : funcFParam (Comma funcFParam)*;

//函数形参
funcFParam
    : bType Ident  # scalarParam
    | bType Ident Lbracket Rbracket (Lbracket exp Rbracket)*  # arrayParam
    ;

//语句块
block : Lbrace blockItem* Rbrace;

//语句块项
blockItem
    : decl
    | stmt
    ;

// 以下文法没有实现的部分请补充完整，请将终结符用词法规则中对应的Token符号代替
//    词法规则定义在SysyLex.g4中

// Stmt → LVal '=' Exp ';'
// | [Exp] ';'
// | Block
// | 'if' '( Cond ')' Stmt [ 'else' Stmt ]
// | 'while' '(' Cond ')' Stmt
// | 'break' ';
// | 'continue' ';'
// | 'return' [Exp] ';'

stmt
    : lVal Assign exp Semicolon  # assign
    | exp? Semicolon  # exprStmt
    | block  # blockStmt
    | If Lparen cond Rparen stmt (Else stmt)?  # ifElse
    | While Lparen cond Rparen stmt  # while
    | Break Semicolon  # break
    | Continue Semicolon  # continue
    | Return exp? Semicolon # return
    ;

// *************** END *********************
//左值表达式
lVal : Ident (Lbracket exp Rbracket)*;

//函数实参表
funcRParams : funcRParam (Comma funcRParam)*;

//函数实参
funcRParam : exp ;

exp //表达式
   : Lparen exp Rparen #parenexp
   | lVal   #lvalexp
   | number #numexp
   | Ident Lparen funcRParams? Rparen #funcRParamsexp
   | unaryOp exp    #unaryOpexp
   | exp (Mul | Div | Mod) exp  #symbolexp
   | exp (Add | Sub) exp #addandsubexp
   ;

//单元操作符
unaryOp
   : Add
   | Sub
   | Not
   ;

//整数
number
    : intConst
    | floatConst
    ;

intConst
    : DecIntConst  # decIntConst
    | OctIntConst  # octIntConst
    | HexIntConst  # hexIntConst
    ;

floatConst
    : DecFloatConst  # decFloatConst
    | HexFloatConst  # hexFloatConst
    ;

//条件表达式
cond
   : exp
   | cond (Lt | Gt | Leq | Geq) cond
   | cond (Eq | Neq) cond
   | cond And cond
   | cond Or cond
   ;
